﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Drawing;

using DotSpatial.Data;

using DotSpatial.Topology;

using System.ComponentModel;
using System.ComponentModel.Design;



namespace FXnaGis
{
    [Serializable]
    /// <summary>
    /// 用于表示所有的矢量图层，直接表示所有的矢量图形，包括点线面
    /// 提供最基础的数据存储与基本绘制，这一切都可以被重写
    /// </summary>
   public  class FVectorLayer:FLayer
    {


       public FVectorLayer(string id):base(id)
       {

           this._isSelectable = true;



           this._shapes = new Dictionary<string, FShape>();

           this._tempVisibleShapes = new List<FShape>();

           this._selectedShapes = new List<FShape>();

       }



       #region 属性





       protected PointStyle _pointStyle = new PointStyle();

         [Category("样式设置"), DisplayName("点")]
       public PointStyle PointStyle
       {
           get { return _pointStyle; }
           set { _pointStyle = value; }
       }

       protected LineStyle _lineStyle = new LineStyle();

         [Category("样式设置"), DisplayName("线条")]
       public LineStyle LineStyle
       {
           get { return _lineStyle; }
           set { _lineStyle = value; }
       }

       protected PolyStyle _polyStyle = new PolyStyle();

        [Category("样式设置"),DisplayName("多边形")]
       public PolyStyle PolyStyle
       {
           get { return _polyStyle; }
           set { _polyStyle = value; }
       }



       protected Dictionary<string, FShape> _shapes;
        [Browsable (false)]
       public Dictionary<string, FShape> Shapes
       {
           get { return _shapes; }
           set { _shapes = value; }
       }

       




      

       /// <summary>
       /// 重要的屏幕区域内的所有图形
       /// </summary>
      protected  List<FShape> _tempVisibleShapes;


       /// <summary>
       /// 可视区域内的所有图形，这样可以提高查找效率
       /// 
       /// </summary>
       public List<FShape> TempVisibleShapes
       {
           get { return _tempVisibleShapes; }
          
       }




       List<FShape> _selectedShapes;

       public List<FShape> SelectedShapes
       {
           get { return _selectedShapes; }


         
       }



       /// <summary>
       /// 取得图层的所有物体的区域范围
       /// </summary>
       public override Extent  Extent
        {
	        get 
	        {
                Extent ext = null;

                foreach (FShape item in this._shapes.Values)
                {

                    if (item.Extent!=null)
                    {

                        if (ext == null)
                        {
                            ext = item.Extent.Clone() as Extent;

                        }
                        else
                        {
                            ext.ExpandToInclude(item.Extent);

                        }

                        
                    }

                  
                    
                }

		         return ext;

	        }
        }


       public override Extent SelectedExtent
       {
           get
           {
               Extent ext = null;

               foreach (FShape item in this._selectedShapes)
               {

                   if (item.Extent != null)
                   {

                       if (ext == null)
                       {
                           ext = item.Extent.Clone() as Extent;

                       }
                       else
                       {
                           ext.ExpandToInclude(item.Extent);

                       }


                   }



               }

               return ext;
           }
       }
     

  



       #endregion






       #region 内部功能函数

       protected override void DoCollsionDectection(FMapArgs args,List<DotSpatial.Data.Extent> regions)
       {
           //清空上一次的绘制
           //绘制前清空的一个好处是，可以利用drawingshape,执行某些高效率的查询服务，比如shape的选择，shape点的分布情况等
           this._tempVisibleShapes.Clear();




           //需要逐一进行碰撞检测，

           foreach (Extent region in regions)
           {

               Envelope env = (Envelope)region.ToEnvelope();

               foreach (FShape shape in _shapes.Values)
               {

                   //使用更精确的碰撞算法

                   if (shape.Intersects(env))
                   {
                       this._tempVisibleShapes.Add(shape);

                   }



               }


           }


           
       }


       protected override void DrawCore(FMapArgs args, List<Extent> regions)
       {

           foreach (FShape shape in this._tempVisibleShapes)
           {

               //用户自行绘制一些东西,以支持单独图形的独立样式

               shape.Draw(args);


               //不在区别绘制

               if (this._isShowLable)
               {
                   shape.DrawLable(args);

               }



           }

          
       }

       protected override void DrawLable(FMapArgs args, List<Extent> regions)
       {

          
       }

       #endregion



       #region 选择系统

       public override void Select(Extent selectedArea, FSelectionMode smode, FSelectionOperationMode omode)
       {
           base.Select(selectedArea, smode, omode);


           //清空上一步选择

           this.UnSelectAll();


           //判断是否可选

           if (!this._isSelectable)
           {
               return;

               
           }




           //需要判断当前图层的可见性，目前不支持冻结，所以暂时只以可见性为基础

           if (this._isVisiable==false)
           {
               return;
               
           }

         

           //执行选择操作,这里我们选用可视区的东西进行捕捉

           foreach (FShape item in this._tempVisibleShapes)
           {

               //注意这里不能这样写，不能使用物体的Extent，因为它是方形，我们需要fshape提供各自的选择碰撞算法

               Envelope env = (Envelope)selectedArea.ToEnvelope();

               if (item.Intersects(env))
               {
                   this._selectedShapes.Add(item);
                   
               }

             
               
           }


       }

       public override void Select(string id, FSelectionMode smode, FSelectionOperationMode omode)
       {
           base.Select(id, smode, omode);




           switch (omode)
           {
               case FSelectionOperationMode.Additive:
                   break;
               case FSelectionOperationMode.Exclude:
                   break;
               case FSelectionOperationMode.Normal:

                   this._selectedShapes.Clear();

                   break;
               default:
                   break;
           }



           switch (smode)
           {
               case FSelectionMode.InterSection:

                   foreach (FShape shape in this._tempVisibleShapes)
                   {
                       


                   }


                   break;
               case FSelectionMode.Winth:



                   break;
               default:
                   break;
           }



       }

     


       public override void UnSelect(string id)
       {
           base.UnSelect(id);

           FShape shape = null;

           foreach (FShape item in this._selectedShapes)
           {
               if (item.Id == id)
               {
                   shape = item;

                   break;

               }

           }

           if (shape != null)
           {
               this._selectedShapes.Remove(shape);

           }


       }


       public override void SelectAll()
       {
           base.SelectAll();

           this._selectedShapes.Clear();

           foreach (FShape item in this._shapes.Values)
           {
               this._selectedShapes.Add(item);

           }
       }

       public override void UnSelectAll()
       {
           base.UnSelectAll();

           this._selectedShapes.Clear();


          
       }



       private void Select(string id)
       {

           if (this._shapes.ContainsKey(id))
           {
               this._selectedShapes.Add(this._shapes[id]);
           }

       }



       #endregion





       #region shape图形的组织工作

       public void ResetShapes(List<FShape> shapes)
       {
           //当发生重置事件时，我们是简单的全部清空，还是根据ID的不同从新赋值以及更新呢

           //这个 是个值得深入思考的问题




           this._shapes.Clear();
         
           this._tempVisibleShapes.Clear();


           this.AddShapeRange(shapes);




           //对于选择做临时处理？感觉这种做法非常的有问题，但也没找到更好的解决方案，先这样吧

           List<FShape> cloneSelected=this._selectedShapes.CloneList();

           this._selectedShapes.Clear();

           foreach (FShape item in cloneSelected)
           {
               if (this._shapes.ContainsKey(item.Id))
               {
                   this._selectedShapes.Add(item);
                   
               }
               
           }


          



 
       }

       public void ResetShape(FShape shp)
       {
           //先更新主逻辑

           if (this._shapes.ContainsKey(shp.Id))
           {
               this._shapes[shp.Id] = shp;
               


           }



           //最后更新选择和可视区域

           for (int i = 0; i < this._tempVisibleShapes.Count; i++)
           {
               if (this._tempVisibleShapes[i] == shp)
               {

                   this._tempVisibleShapes[i] = shp;
                   break;

               }

           }

           for (int j = 0; j < this._selectedShapes.Count; j++)
           {
               if (this._selectedShapes[j]==shp)
               {

                   this._selectedShapes[j] = shp;

                   break;

               }
               
           }





          
       }

       public void AddShape(FShape shape)
       {

           if (this._shapes.ContainsKey(shape.Id))
           {

               throw new Exception("shape图形已经存在！");


           }
           else
           {

               shape.Parent = this;

               this._shapes.Add(shape.Id,shape);

               this.AskRefresh();
 

           }
          
 


       }

       public FShape GetShapeById(string id)
       {

           if (this._shapes.ContainsKey(id))
           {

               return this._shapes[id];

           }
           else
           {

               return null;
 

           }
          

         

 
       }

       public void RemoveShapeById(string id)
       {

           if (this._shapes.ContainsKey(id))
           {

               FShape shp = this._shapes[id];
               shp.Parent = null;


               this._shapes.Remove(id);

           }
           else
           {

               throw new Exception("不存在对应的shape");


           }
       }


       public void AddShapeRange(List<FShape> shapes)
       {
           foreach (FShape item in shapes)
           {
               this.AddShape(item);
               
           }
 
       }


        #endregion




    }


}
